<?php
/**
 * User: papa
 * Date: 18/5/21
 * Time: 17:06
 */

namespace app\api\service;


use app\admin\model\GoodsSpecPrice;
use app\admin\model\UserLevel;
use app\api\lib\exception\MissException;
use app\api\lib\exception\SuccessMessage;
use app\api\model\CouponCategory;
use app\api\model\CouponTickets;
use app\api\model\FacePay;
use app\api\model\Goods;
use app\api\model\Order;
use app\api\model\Payset;
use app\api\model\User;
use app\api\model\UserCharge;
use app\api\model\Collage;
use think\Db;

class OrderService
{
    //检测优惠券是否开启(张亚博)
    public static function doPaySet($user)
    {
        $set = Payset::find();
        if(!$set) throw new MissException(['msg' => '缺失关键数据库数据']);
        if($set->allow_coupon == 0){    //后台禁止使用优惠劵
            $coupon['status'] = 'close';  //设置关闭状态
        }else{
            $coupon['status'] = 'ok';
            $couponIds = CouponTickets::getUserAvailableCoupon($user);
            $data = CouponTickets::with(['couponCate','activity'=>function($qa){
                $qa->field('id,end_time');
            }])->field('id,activity_id,coupon_category_id')->where('id','in',$couponIds)->select();
            $res = [];
            foreach($data as $k=>$v){
                $res[$k]['id'] = $v->getData('id');
                $res[$k]['coupon_cate_cate'] = $v->coupon_cate->getData('coupon_cate_cate');
                $res[$k]['amount_cash'] = $v->coupon_cate->getData('amount_cash');
                $res[$k]['discount_ticket'] = $v->coupon_cate->getData('discount_ticket');
                $res[$k]['low_price'] = $v->coupon_cate->getData('low_price');
                $res[$k]['name'] = $v->coupon_cate->getData('name');
                $res[$k]['end_time'] = $v->activity->getData('end_time');
            }
            $coupon['data'] = $res;
        }
        return ['coupon'=>$coupon];
    }



    public static function doPaySet1($user)
    {
        $set = Payset::find();
        if(!$set) throw new MissException(['msg' => '缺失关键数据库数据']);
        if($set->allow_coupon == 0){    //后台禁止使用优惠劵
            $coupon['status'] = 'close';  //设置关闭状态
        }else{
            //正常使用，返回用户当前优惠劵列表
            $coupon['status'] = 'ok';
            //获取可用优惠劵
            $coupon['data'] = CouponTickets::useCoupon($user->id);
        }
        return ['coupon'=>$coupon];
    }

    /********************************************价格处理部分**************************************************/
    //价格处理接口（张亚博）
    public static function handlePrice($data,$user)
    {
        //用户价格处理的顺序问题
        //1.先使用优惠券，在计算用户折扣
        $check = self::doPaySet($user);
        if($check['coupon']['status'] !== 'ok'){
            throw new MissException(['msg'=>'后台优惠券活动已关闭！']);
        }
        $price = self::foodTotalPrice($data);
        if(!empty($data['coupon_id'])){
            $coupon = CouponTickets::checkForCoupon($data['coupon_id'],$user->getData('id'));
            //处理优惠券
            if(($coupon != false) && is_array($coupon)){
                switch($coupon['coupon_cate']){
                    case 1:
                        $price = $price - $coupon['amount_cash'];
                        break;
                    case 2:
                        $price = $price * $coupon['discount_ticket'];
                        break;
                    default:
                }
            }
        }
        if(is_float($price)){
            $price = round($price,2);
        }
        if($price < 0.01){
            $price = 0.01;
        }
        return new SuccessMessage(['data'=>$price]);
    }
    //计算价格接口
    public static function handlePrice1($data,$user)
    {
        //对用户的订单和优惠劵进行检测
        self::checkFacePayData($data,$user);
        //加上优惠劵满减金额
        $coupon_price = self::couponPrice($data);
        if(is_float($coupon_price)){
            //先打折，在减积分
            $res =  self::foodTotalPrice($data) * $coupon_price;
        }else {
            //满减
            $res =  self::foodTotalPrice($data)- $coupon_price;
        }
//        $levelRule = self::levelPrice($user);
        //用户当前等级的打折规则
//        $res = $res * $levelRule;
        //防止负数
        if($res < 0){
            $res = 0.01;
        }
        return new SuccessMessage(['data'=>$res]);
    }

    //根据用户等级，来获取打折规则
    public static function levelPrice($user)
    {
        //获取对应等级
        $userLevel = UserLevel::get($user->level_id);
        return $userLevel->rate;
    }

     // 对前端请求过来的优惠劵信息进行安全校验
    public static function checkFacePayData1($data,$user){
        if(empty($data['coupon_id'])){
            return false;
        }
        $set = Payset::find();
        if(!$set) throw new MissException(['msg' => '缺失关键数据库数据']);
        if($set->allow_coupon == 0){    //后台禁止使用优惠劵
            return false;
        }

        $res = CouponTickets::checkForCoupon($data['coupon_id'],$user->id);
        if($res && is_array($res)){
            if($res['coupon_cate'] == 1){
                if($data['price'] < $res['low_price']){
                    return false;
                }
            }
        }
        return true;
    }


    public static function checkFacePayData($data,$user)
    {
        $check = self::doPaySet($user);
        //如果传递有优惠劵
        if(!empty($data['coupon_id'])){
            //查询后台是否开启
            if($check['coupon']['status'] == 'ok'){
                //查询用户是否有优惠劵或者是否已用或者过期
                $res = CouponTickets::checkCoupon($data['coupon_id'],$user->id);
                if(!$res){
                    throw new MissException(['msg'=>'优惠劵不存在或者已过期']);
                }
                //如果是满减类型，并且满减金额小于当前订单金额
                if($res->couponCate->coupon_cate_cate == 1){
                    //如果结算金额不符合优惠劵规则
                    if($res->couponCate->low_price > $data['price']){
                        throw new MissException(['msg' => '使用的优惠劵不符合条件']);
                    }
                    //如果是无门槛优惠
                    if($res->couponCate->low_price == 0){
                        return true;
                    }
                }
            }else{
                throw new MissException(['msg' => '后台没有开启使用优惠劵']);
            }
        }
        return true;
    }

    //在无优惠的情况下获取商品的总价
    public static function foodTotalPrice($data)
    {
        //判断是否是拼团
        if(!empty($data['collage'] )){
            $collage = Collage::find($data['collage']);
            return $collage->getData('collage_price');
        }
        $price = null;
        //获取全部商品数据
        foreach ($data['food'] as $key=>$val) {
            $food = Goods::get($val['food_id']);
            //如果有规格
            if(!empty($val['spec_item'])){
                $specPrice = GoodsSpecPrice::get(['goods_id'=>$val['food_id'],'spec_item_ids'=>$val['spec_item']]);
                $price += $val['count'] * $specPrice->price;
                if($val['count'] < $val['count']){
                    $price = $price + 10;
                }
            }else {
                //没有商品规格
                $price += $food->sale_price * $val['count'];
                if($val['count'] < $food['exemption']){
                    $price = $price + 10;
                }
            }
        }
        return $price;
    }

    //优惠劵减去的金额
    public static function couponPrice($data)
    {
        if(array_key_exists('coupon_id',$data) ){
            $coupon = CouponCategory::get($data['coupon_id']);
            //根据优惠劵模型判断是打折还是满减
            if($coupon->coupon_cate_cate == 1) {
                //返回满减金额
                return $coupon->amount_cash;
            }elseif ($coupon->coupon_cate_cate == 2){
                //返回打折数
                return $coupon->discount_ticket;
            }
        }else{
            return 0;
        }
    }

/*********************************************订单处理部分*************************************************/
    //商品支付生成订单
    public static function foodOrder($data,$user)
    {
        if(array_key_exists('coupon_id',$data) && (!empty($data['coupon_id']))){
            //检查发送过来的优惠劵和积分是否有效
            if(!self::checkFacePayData1($data, $user)){
                throw new MissException(['msg'=>'优惠券检测失败!']);
            }
        }

        //获取优惠后的价格重新赋值
        $true_price = self::handlePrice($data,$user);
        $true_price = $true_price->data;
        if(is_float($true_price)){
            //排除小数点超出两位
            $data['true_price'] = round($true_price,2);
        }else{
            $data['true_price'] = $true_price;
        }
        //检测用户id是否一致
        $data['user_id'] = $user->id;
        //当担初始状态，未付款
        $data['status'] = 1;
        $data['sn'] = OrderService::makeOrderNo();
        $food = $data['food'];  //  取出商品
        unset($data['food']);   //销毁，因为新增没有使用字段过滤

        if(array_key_exists('collage',$data) && (!empty($data['collage']))){
//            unset($data['collage']);
            $data['collage'] = 0;
        }else{
            $data['collage'] = 1;
        }
        Db::startTrans();
        try{
            $order = Order::create($data);
            $order->orderDetail()->saveAll($food);
            if(array_key_exists('coupon_id',$data) && (!empty($data['coupon_id']))) {
                CouponTickets::where('id', 'eq', $data['coupon_id'])->update(['is_use' => 1]);
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            throw new MissException(['msg'=>'订单创建失败!']);
        }
        if($data['type'] == 1){
            (new Pay())->OrderPay($data['sn']);
        }
        if($data['type'] == 2){
            self::handleAccount($data,$user);
        }
        throw new MissException(['msg'=>'错误的参数!']);
    }

    //处理余额支付的订单
    public static function handleAccount($data,$user)
    {
        //余额支付的规则说明
        //1.使用充值余额支付
        //2.充值余额不足时使用赠送余额
        $account_money = $user->getData('account_money');
        $charge_money = $user->getData('charge_money');
        $donate_money = $user->getData('donate_money');
        $true_price = $data['true_price'];
        if($account_money < $true_price){
            throw new MissException(['msg'=>'账户余额不足']);
        }else{
            if($charge_money >= $true_price){
                $new_charge_money = $charge_money - $true_price;
                $new_account_money = $account_money - $true_price;
                Db::startTrans();
                try{
                    User::where(['id'=>$user->getData('id')])->update(['charge_money'=>$new_charge_money,'account_money'=>$new_account_money]);
                    Order::where(['sn'=>$data['sn']])->update(['status'=>2]);
                    Db::commit();
                } catch (\Exception $e) {
                    Db::rollback();
                    throw new MissException(['msg'=>'余额支付异常!,请稍后再试']);
                }
                throw new SuccessMessage(['data'=>'余额支付成功!']);
            }else{
                $disparity = $true_price - $charge_money;
                if($donate_money > $disparity){
                    $new_charge_money = 0;
                    $new_donate_money = $donate_money-$disparity;
                    $new_account_money = $account_money - $disparity - $charge_money;
                    Db::startTrans();
                    try{
                        User::where(['id'=>$user->getData('id')])->update(['charge_money'=>$new_charge_money,'donate_money'=>$new_donate_money,'account_money'=>$new_account_money]);
                        Order::where(['sn'=>$data['sn']])->update(['status'=>2]);
                        Db::commit();
                    } catch (\Exception $e) {
                        Db::rollback();
                        throw new MissException(['msg'=>'余额支付异常!,请稍后再试']);
                    }
                    throw new SuccessMessage(['data'=>'余额支付成功!']);
                }else{
                    throw new MissException(['msg'=>'系统数据异常,请联系管理员!']);
                }
            }
        }
    }

    //生成添加当面付订单
    public static function createFaceOrder($data,$sn,$result,$user)
    {
        $data['prepay_id'] = $result['prepay_id'];; //预支付参数
        $data['user_id'] = $user->id;   //  用户id
        $data['sn'] = $sn;  //当面付订单号
        $data['true_price'] = (self::handlePrice($data,$type = 'face',$user))->data;
        if(FacePay::create($data)){
            return true;
        }else{
            throw new MissException(['msg'=>'添加订单异常']);
        }
    }

    //未付款订单发起支付，对订单号进行系列检测
    public static function checkSn($sn,$user)
    {
        $order = \app\admin\model\Order::get(['sn'=>$sn,'user_id'=>$user->id]);
        if(!$order){
            throw new MissException(['msg'=>'订单不存在，或者不属于当前用户']);
        }
        //订单不是未付款状态
        if($order->status != 1){
            throw new MissException(['msg'=>'该订单已被处理']);
        }

    }
    
    //付款成功后的数据修改，包含优惠劵，积分减去
    public static function facePayOrderChange($order)
    {
        //开启事务，防止部分更新
        Db::transaction(function() use($order){
            $user = User::get($order->user_id);
            $set = Payset::find();
            if($set->allow_points == 1) {
                //修改用户积分
                if (!empty($order->points)) $user->setDec('points', $order->points);
                //获取订单金额，增加用户积分
                $user->setInc('points', intval($order->price / $set->need_rmb));
            }
            if($set->allow_coupon == 1) {
                //如果使用了优惠劵，则修改用户对应优惠劵的状态
                if (!empty($order->coupon_id)) {
//                    $coupon = CouponTickets::get(['user_id' => $user->id, 'cate_id' => $order->coupon_id]);
                    $coupon = CouponTickets::where('id','eq',$order->coupon_id)->find();
                    $coupon->is_use = 1;
                    $coupon->save();
                }
            }

            foreach ($order->detail as $v) {
                $goods = \app\admin\model\Goods::get($v->food_id);
                $goods->setInc('sales_num',$v->count);
            }
            $order->status = 2; //当面付订单状态
            $order->save();
        });
    }

    //理论上生成不重复的订单号
    public static function makeOrderNo($type = 'order')
    {
        $sn = null;
        while (true){
            $sn = date('Ymd').mt_rand(100000,999999);
            if($type == 'order') {  //外卖，堂食，自取订单
                $order_count = Order::where(['sn' => $sn])->count();
            }elseif ($type == 'deposit'){   //当面付订单
                $order_count = UserCharge::where(['sn'=>$sn])->count();
            }
            if($order_count == 0) break;
        }
        return $sn;
    }

    //校验订单是否是当前用户的
    public static function checkOrderInUser($order_id){
        $res = Order::get($order_id);
        if(!$res){
            throw new MissException();
        }
        $uid = TokenService::getCurrentUid();
        if($res['user_id'] != $uid){
            throw new MissException([
                'msg' => '非法请求',
            ]);
        }
        return $res;
    }

    //根据传递菜品的id获取菜品原始详细信息
    public function getFoodsByOrder($foods)
    {
        $id = [];
        foreach ($foods as $food) {
            array_push($id,$food['food_id']);
        }
        $order_foods = Goods::all($id);
        //获取订单中菜品详细数据
        return collection($order_foods)->toArray();
    }
}